package my.mall.admin.api.service

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper
import my.mall.admin.api.pojo.admin.AdminDetail
import my.mall.admin.api.pojo.admin.ResourceItem
import my.mall.admin.api.pojo.resource.ResourceTypeEnum
import my.mall.common.enums.RespMetaEnum
import my.mall.common.exception.WebBaseException
import my.mall.db.entity.*
import my.mall.db.mapper.*
import org.springframework.stereotype.Service
import org.springframework.util.CollectionUtils
import java.util.*
import java.util.stream.Collectors

@Service
open class AdminService(
    private val storeClerkMapper: StoreClerkMapper,
    private val roleClerkMapper: RoleClerkMapper,
    private val resourceMapper: ResourceMapper,
    private val roleResourceMapper: RoleResourceMapper,
    private val adminMapper: AdminMapper,
) {

    open fun getAdminInfo(storeId: Long, adminId: Long): AdminDetail {
        val admin = adminMapper.selectOne(
            QueryWrapper<Admin>()
                .select(
                    Admin.ID,
                    Admin.NICK_NAME,
                )
                .eq(Admin.ID, adminId)
        ) ?: throw WebBaseException(RespMetaEnum.PARAM_ERROR)
        val adminDetail = AdminDetail(admin.id!!, admin.nickName!!)
        val resourceList = getResourceList(storeId, adminId)
        if (resourceList.isEmpty()) {
            return adminDetail
        }
        val childList: MutableList<Resource> = ArrayList()
        val resourceInfoMap: MutableMap<Long, ResourceItem> = HashMap()
        for (resource in resourceList) {
            if (ResourceTypeEnum.FIRST_MENU.type == resource.resourceType) {
                val resourceItem = ResourceItem()
                resourceItem.resourceKey = resource.resourceKey
                resourceItem.resourceLabel = resource.resourceLabel
                adminDetail.menuAuthList.add(resourceItem)
                resourceInfoMap[resource.id!!] = resourceItem
            } else if (ResourceTypeEnum.SECOND_MENU.type == resource.resourceType) {
                childList.add(resource)
            } else if (ResourceTypeEnum.BUTTON.type == resource.resourceType) {
                adminDetail.buttAuthList.add(resource.resourceKey!!)
            }
        }
        for (resource in childList) {
            val resourceItem = resourceInfoMap[resource.parentId]
            if (resourceItem != null) {
                val child = ResourceItem()
                child.resourceKey = resource.resourceKey
                child.resourceLabel = resource.resourceLabel
                resourceItem.childList.add(child)
            }
        }
        return adminDetail
    }

    open fun getResourceList(storeId: Long, adminId: Long): List<Resource> {
        val clerk = storeClerkMapper.selectOne(
            QueryWrapper<StoreClerk>()
                .select(
                    StoreClerk.ID,
                    StoreClerk.NICK_NAME,
                )
                .eq(StoreClerk.STORE_ID, storeId)
                .eq(StoreClerk.ADMIN_ID, adminId)
        ) ?: return Collections.emptyList()
        val roleClerkList = roleClerkMapper.selectList(
            QueryWrapper<RoleClerk>()
                .select(
                    RoleClerk.ROLE_ID,
                )
                .eq(RoleClerk.CLERK_ID, clerk.id)
        )
        val roleIds = roleClerkList.stream().map(RoleClerk::roleId).collect(Collectors.toList())
        if (CollectionUtils.isEmpty(roleIds)) {
            return Collections.emptyList()
        }
        val roleResourceList = roleResourceMapper.selectList(
            QueryWrapper<RoleResource>()
                .select(
                    RoleResource.RESOURCE_ID,
                )
                .`in`(RoleResource.ROLE_ID, roleIds)
        )
        val resourceIds = roleResourceList.stream().map(RoleResource::resourceId).collect(Collectors.toList())
        return if (CollectionUtils.isEmpty(resourceIds)) {
            Collections.emptyList()
        } else resourceMapper.selectList(
            QueryWrapper<Resource>()
                .select(
                    Resource.ID,
                    Resource.RESOURCE_KEY,
                    Resource.RESOURCE_LABEL,
                    Resource.RESOURCE_TYPE,
                    Resource.PARENT_ID,
                )
                .`in`(Resource.ID, resourceIds)
        )
    }
}
